package com.example.djetpack.livedata

import androidx.lifecycle.*
import java.util.concurrent.ConcurrentHashMap


/**
 * Author: shuhong
 * Date: 2020/9/10 11:27
 * Description:
 */
object HiEventBus {

    private val mEventMap: ConcurrentHashMap<String, StickyLiveData<*>> = ConcurrentHashMap()

    fun <T> with(eventName: String): StickyLiveData<T> {
        var liveData = mEventMap[eventName]
        if (liveData == null) {
            liveData = StickyLiveData<T>(eventName)
            mEventMap[eventName] = liveData
        }

        return liveData as StickyLiveData<T>
    }

    class StickyLiveData<T>(private val eventName: String) : LiveData<T>() {

        internal var mStickyData: T? = null
        internal var mVersion = 0

        fun setStickyData(stickyData: T) {
            mStickyData = stickyData
            setValue(stickyData)
        }

        fun postStickyData(stickyData: T) {
            mStickyData = stickyData
            postValue(stickyData)
        }

       public  override fun postValue(value: T) {
            mVersion++
            super.postValue(value)
        }

        public override fun setValue(value: T) {
            mVersion++
            super.setValue(value)
        }

        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            observeSticky(owner, false, observer)
        }

        fun observeSticky(owner: LifecycleOwner, sticky: Boolean, observer: Observer<in T>) {
            owner.lifecycle.addObserver(LifecycleEventObserver { source, event ->
                if (event == Lifecycle.Event.ON_DESTROY) {
                    mEventMap.remove(eventName)
                }
            })
            super.observe(owner, StickyObserver(this, sticky, observer))
        }
    }

    class StickyObserver<T>(
        val stickyLiveData: StickyLiveData<T>,
        val sticky: Boolean,
        val observer: Observer<in T>
    ) : Observer<T> {

        private var lastVersion = stickyLiveData.mVersion

        override fun onChanged(t: T) {
            if (lastVersion >= stickyLiveData.mVersion) {
                if (sticky && stickyLiveData.mStickyData != null) {
                    observer.onChanged(t)
                }
                return
            }

            lastVersion = stickyLiveData.mVersion
            observer.onChanged(t)
        }

    }
}